// 定义节流选项接口，明确类型
export interface ThrottleOptions {
    leading?: boolean; // 是否在节流开始时立即执行
    trailing?: boolean; // 是否在节流结束时延迟执行
}

// 泛型定义节流函数类型
export type ThrottledFunction<T extends (...args: any[]) => any> = (
    ...args: Parameters<T>
) => ReturnType<T> | undefined;

/**
 * 优化后的节流函数
 * @param func 目标函数
 * @param wait 节流时间间隔（毫秒）
 * @param options 节流选项（leading/trailing）
 * @returns 节流后的函数（包含cancel方法）
 */
export const throttle = function <T extends (...args: any[]) => any>(
    func: T,
    wait: number,
    options?: ThrottleOptions
): ThrottledFunction<T> & { cancel: () => void } {
    let timeout: number | null = null;
    let lastArgs: Parameters<T> | null = null; // 使用精确的参数类型
    let result: ReturnType<T> | undefined;
    let previous = 0;

    // 默认选项：默认开启leading和trailing
    const { leading = true, trailing = false } = options || {};

    // 清除所有状态
    const clear = () => {
        if (timeout) {
            clearTimeout(timeout);
            timeout = null;
        }
        previous = 0;
        lastArgs = null;
    };

    // 延迟执行逻辑
    const later = (thisArg: any) => {
        previous = leading === false ? 0 : Date.now();
        timeout = null;
        if (lastArgs && trailing) {
            result = func.apply(thisArg, lastArgs);
            lastArgs = null;
        }
    };

    const throttled = function (this: any, ...args: Parameters<T>): ReturnType<T> | undefined {
        const now = Date.now();

        // 首次调用且禁用leading时初始化时间
        if (!previous && leading === false) previous = now;

        const remaining = wait - (now - previous);
        lastArgs = args; // 保存当前参数

        // 当剩余时间 <= 0 时，需要立即执行（leading逻辑）
        if (remaining <= 0 || remaining > wait) {
            if (timeout) {
                clearTimeout(timeout);
                timeout = null;
            }
            previous = now;
            result = func.apply(this, args);
            lastArgs = null;
        }
        // 否则检查是否需要设置延迟执行（trailing逻辑）
        else if (!timeout && trailing) {
            // 直接传递当前this上下文，避免别名化
            timeout = window.setTimeout(() => later(this), remaining);
        }

        return result;
    };

    // 取消防节流（清除计时器和状态）
    throttled.cancel = () => {
        clear();
    };

    return throttled;
};
export type DebounceOptions = {
    leading?: boolean; // 是否在第一次触发时立即执行
    trailing?: boolean; // 是否在最后一次触发后执行
    maxWait?: number; // 最大等待时间
};

// 泛型定义防抖函数类型
export type DebouncedFunction<T extends (...args: any[]) => any> = (
    ...args: Parameters<T>
) => ReturnType<T> | undefined;

export const debounce = function <T extends (...args: any[]) => any>(
    func: T,
    wait: number,
    options?: DebounceOptions
): DebouncedFunction<T> & {
    cancel: () => void;
    flush: () => ReturnType<T> | undefined;
} {
    // 默认选项：默认开启trailing，关闭leading
    const { leading = false, trailing = true, maxWait } = options || {};
    let timeout: number | null = null;
    let lastArgs: Parameters<T> | null = null;
    let lastCallTime = 0;
    let result: ReturnType<T> | undefined;

    const clear = () => {
        if (timeout) {
            clearTimeout(timeout);
            timeout = null;
        }
        lastCallTime = 0;
        lastArgs = null;
    };

    const invokeFunc = (time: number, thisArg: any) => {
        const args = lastArgs;
        if (args) {
            lastArgs = null;
            result = func.apply(thisArg, args);
        }
        lastCallTime = time;
        return result;
    };

    const startTimer = (
        pendingFunc: (time: number, thisArg: any) => void,
        delay: number,
        thisArg: any
    ) => {
        timeout = window.setTimeout(() => pendingFunc(Date.now(), thisArg), delay);
    };

    const leadingEdge = (time: number, thisArg: any) => {
        lastCallTime = time;
        startTimer(trailingEdge, wait, thisArg);
        return leading ? invokeFunc(time, thisArg) : result;
    };

    const trailingEdge = (time: number, thisArg: any) => {
        timeout = null;
        if (trailing && lastArgs) {
            return invokeFunc(time, thisArg);
        }
        clear();
        return result;
    };

    const remainingWait = (time: number) => {
        const timeSinceLastCall = time - lastCallTime;
        const timeWaiting = wait - timeSinceLastCall;
        return maxWait ? Math.min(timeWaiting, maxWait - (time - lastCallTime)) : timeWaiting;
    };

    // 确保debounced始终是一个函数
    const debounced = function (this: any, ...args: Parameters<T>): ReturnType<T> | undefined {
        // 确保传入的参数正确
        if (typeof args === 'undefined') {
            lastArgs = [] as unknown as Parameters<T>;
        } else {
            lastArgs = args;
        }

        const time = Date.now();
        lastCallTime = lastCallTime || time;

        const remaining = remainingWait(time);

        if (remaining <= 0 || remaining > wait) {
            if (timeout) {
                clearTimeout(timeout);
                timeout = null;
            }
            leadingEdge(time, this);
        } else if (!timeout && trailing) {
            startTimer(trailingEdge, remaining, this);
        }

        return result;
    };

    debounced.cancel = () => {
        if (timeout) clearTimeout(timeout);
        clear();
    };

    debounced.flush = function (this: any) {
        if (timeout) {
            const result = invokeFunc(Date.now(), this);
            clear();
            return result;
        }
        return result;
    };

    // 确保返回的是一个函数，并且附加了方法
    return debounced as DebouncedFunction<T> & {
        cancel: () => void;
        flush: () => ReturnType<T> | undefined;
    };
};
